package org.convallaria.infrastruct.ce.config;

import io.micrometer.core.instrument.MeterRegistry;
import lombok.extern.slf4j.Slf4j;
import org.convallaria.infrastruct.ce.properties.CacheProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.concurrent.atomic.AtomicLong;

/**
 * 缓存监控配置类
 * 提供缓存性能监控和指标收集
 * 
 * @author gjh
 * @since 2024-09-24
 */
@Slf4j
@Configuration
@EnableScheduling
@ConditionalOnClass({CacheManager.class, MeterRegistry.class})
@ConditionalOnBean({CacheManager.class, MeterRegistry.class})
public class CacheMonitoringConfig {

    private final CacheProperties cacheProperties;
    @SuppressWarnings("unused")
    private final CacheManager cacheManager;
    @SuppressWarnings("unused")
    private final MeterRegistry meterRegistry;
    
    // 缓存统计指标
    private final AtomicLong cacheHits = new AtomicLong(0);
    private final AtomicLong cacheMisses = new AtomicLong(0);
    private final AtomicLong cacheEvictions = new AtomicLong(0);

    @Autowired
    public CacheMonitoringConfig(CacheProperties cacheProperties, 
                                CacheManager cacheManager, 
                                MeterRegistry meterRegistry) {
        this.cacheProperties = cacheProperties;
        this.cacheManager = cacheManager;
        this.meterRegistry = meterRegistry;
    }

    /**
     * 自定义MeterRegistry配置
     */
    @Bean
    public MeterRegistryCustomizer<MeterRegistry> cacheMetricsCustomizer() {
        return registry -> {
            // 注册缓存指标 - 使用简化的方式
            registry.gauge("cache.hits", cacheHits);
            registry.gauge("cache.misses", cacheMisses);
            registry.gauge("cache.evictions", cacheEvictions);
            
            // 计算命中率
            registry.gauge("cache.hit.ratio", this, CacheMonitoringConfig::getHitRatio);
        };
    }

    /**
     * 定期收集缓存统计信息
     */
    @Scheduled(fixedDelayString = "${convallaria.cache.monitoring.metrics-interval:PT1M}")
    public void collectCacheMetrics() {
        if (cacheProperties != null && !cacheProperties.getMonitoring().isEnabled()) {
            return;
        }

        try {
            // 这里可以收集更详细的缓存统计信息
            // 例如：各缓存的大小、命中率、过期时间等
            log.debug("收集缓存统计信息 - 命中: {}, 未命中: {}, 驱逐: {}", 
                    cacheHits.get(), cacheMisses.get(), cacheEvictions.get());
            
            // 可以在这里添加更复杂的统计逻辑
            // 例如：遍历所有缓存，收集详细信息
            
        } catch (Exception e) {
            log.warn("收集缓存统计信息时发生错误", e);
        }
    }

    /**
     * 获取命中率
     */
    public double getHitRatio() {
        long hits = cacheHits.get();
        long misses = cacheMisses.get();
        long total = hits + misses;
        return total > 0 ? (double) hits / total : 0.0;
    }

    /**
     * 记录缓存命中
     */
    public void recordCacheHit() {
        cacheHits.incrementAndGet();
    }

    /**
     * 记录缓存未命中
     */
    public void recordCacheMiss() {
        cacheMisses.incrementAndGet();
    }

    /**
     * 记录缓存驱逐
     */
    public void recordCacheEviction() {
        cacheEvictions.incrementAndGet();
    }

    /**
     * 获取缓存统计信息
     */
    public CacheStatistics getCacheStatistics() {
        return CacheStatistics.builder()
                .hits(cacheHits.get())
                .misses(cacheMisses.get())
                .evictions(cacheEvictions.get())
                .hitRatio(cacheHits.get() + cacheMisses.get() > 0 ? 
                        (double) cacheHits.get() / (cacheHits.get() + cacheMisses.get()) : 0.0)
                .build();
    }

    /**
     * 缓存统计信息
     */
    @lombok.Data
    @lombok.Builder
    public static class CacheStatistics {
        private long hits;
        private long misses;
        private long evictions;
        private double hitRatio;
    }
}
